﻿#pragma once
#include <string>
#include <vector>

#include "lix/lix.h"

#include "lix/char_sequence.h"
#include "lix/chunk/fixed_allocator.h"
#include "lix/xml/node.h"


namespace lix{
	namespace xml{

// いくら namespace に入れるとはいえ、さすがに Document は特等席すぎるのではないかと思った。
class XmlDocument;
class NodeAllocator;


// パース結果
enum ParseResult {
	kParseOK = 0,				//!< 成功
	kParseAllocationFailed = 1,	//!< メモリ関連の失敗
	kParseEmptyText = 2,		//!< xmlの要素が何もない
	kParseNoEndTag = 3,			//!< 開きタグが閉じてない
	kParseInvalidEndTag = 4,	//!< 開きタグと閉じタグが対応してない
	kParseInvalidTagFormat = 5, //!< タグ自体のフォーマットがおかしい
	kParseInvalidAttribute = 6,
	kParseNone,
};



// パースオプション
namespace option{
	enum{
		kSkipEmptyTextNode = 1,
		kSkipMixedWhiteSpace = 2,
		kSkipDoctype = 4,
		kSkipXmlDeclare = 8,
		kSkipComment = 16,
		kSkipPI = 32,	
	};
}



//! ドキュメントに紐付けられたアロケータインターフェース。
//! 
//! 実体は NodeAllocator だが、外部公開してクライアントが使用することを可能にするために、
//! このインターフェースを用意する。
class IDocumentLocalAllocator {
public:
	virtual ~IDocumentLocalAllocator(){};

	//! allocateItem で返却されるメモリのサイズ
	virtual size_t getItemSize() = 0;

	//! アロケート。
	//! 
	//! XmlDocument と紐付く getItemSize で返却されるバイト数のメモリを取得する。
	//! クライアントは領域を自由に使用でき、不要になったら deallocateItem で削除するが、
	//! XmlDocument が破棄されると一緒に無効化されるので注意。
	virtual void* allocateItem() = 0;

	// デアロケート
	virtual void deallocateItem( void* p ) = 0;
};








//! XmlDocument
class XmlDocument : public Node{
public:

	//! デフォルトコンストラクタ
	XmlDocument();

	//! デストラクタ
	~XmlDocument();


	ParseResult parse( const std::string& text, uint32_t options = 0);
	ParseResult parse( const char* pch, uint32_t options = 0 );
	ParseResult parse( lix::CharSequence sequence, uint32_t options = 0 );
	

	//! パース対象文字列を返す。
	const char* getSourceString() const;

	// ドキュメントに紐つけたメモリ割り当てをするアロケータを返す。
	IDocumentLocalAllocator* getLocalAllocator();
	
private:
	LIX_DEF_COPY_AND_ASSIGN( XmlDocument );
	
	ParseResult parseImpl(uint32_t options);

	ParseResult m_Result;
	std::vector<char> m_Text;
	
	NodeAllocator* m_Allocator;
	
};













	
}} // namespace  lix::xml